package com.sicent.operate.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Tuple;

/**
 * redisutils
 * @author wangbo
 *
 */
public class RedisUtils {

	private static JedisPool pool;

	private static final Integer DEFAULT_REDIS_TIMEOUT = 20 * 60 * 1000;
	
	private static String redisConfigFileName;
	private static String redisNode;
	
	static{
		initRedisPool("config/redis", "base");
	}

	private  static String getConfigValue(String key, ResourceBundle bundle) {
		String value = bundle.getString(key);
		if (StringUtils.isBlank(value)) {
			value = "";
		}
		System.out.println("File:"+redisConfigFileName+".properties*****redisNode:"+redisNode+"********Key:" + key
				+ "************value:" + value.trim());
		return value.trim();
	}

	protected static void initRedisPool(String redisConfigFileName , String redisNode) {
		System.out.println("Begin to init redis pool,file name:"+redisConfigFileName+",prefix:"+redisNode+".........");
		RedisUtils.redisConfigFileName=redisConfigFileName;
		RedisUtils.redisNode=redisNode;
		ResourceBundle bundle = ResourceBundle.getBundle(redisConfigFileName);
		if (bundle == null) {
			throw new IllegalArgumentException("File:" + redisConfigFileName
					+ ".properties not found");
		}
		JedisPoolConfig config = new JedisPoolConfig();

		String maxActive = getConfigValue("redis.pool.maxActive", bundle);
		if (StringUtils.isNotBlank(maxActive)) {
			config.setMaxTotal(Integer.valueOf(maxActive));
		}

		String maxIdle = getConfigValue("redis.pool.maxIdle", bundle);
		if (StringUtils.isNotBlank(maxIdle)) {
			config.setMaxIdle(Integer.valueOf(maxIdle));
		}

		String minIdle = getConfigValue("redis.pool.minIdle", bundle);
		if (StringUtils.isNotBlank(minIdle)) {
			config.setMinIdle(Integer.valueOf(minIdle));
		}

		String maxWait = getConfigValue("redis.pool.maxWait", bundle);
		if (StringUtils.isNotBlank(maxWait)) {
			config.setMaxWaitMillis(Long.valueOf(maxWait));
		}

		String testOnBorrow = getConfigValue("redis.pool.testOnBorrow", bundle);
		if (StringUtils.isBlank(testOnBorrow)) {
			config.setTestOnBorrow(Boolean.valueOf(testOnBorrow));
		}

		String testOnReturn = getConfigValue("redis.pool.testOnReturn", bundle);
		if (StringUtils.isNotBlank(testOnReturn)) {
			config.setTestOnReturn(Boolean.valueOf(testOnReturn));
		}

		String ip = getConfigValue(redisNode+".redis.ip", bundle);
		String port = getConfigValue(redisNode+".redis.port", bundle);
		String readTimeOut = getConfigValue("redis.pool.timeout", bundle);
		
		if (StringUtils.isBlank(readTimeOut)) {
			readTimeOut = DEFAULT_REDIS_TIMEOUT.toString();
		}
		pool = new JedisPool(config, ip, Integer.valueOf(port),
				Integer.valueOf(readTimeOut));
		
		System.out.println("End to init redis pool,file name:"+redisConfigFileName+",prefix:"+redisNode+".........");
	}

	public static void returnResource(JedisPool pool, Jedis jedis) {
		if (jedis != null) {
			pool.returnResource(jedis);
		}
	}

	public static String get(String key) {
		Jedis jedis = null;
		String value = null;
		try {
			jedis = pool.getResource();
			value = jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return value;
	}

	public static void setAndExpire(String key, String value, int seconds) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.set(key, value);
			jedis.expire(key, seconds);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static void set(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.set(key, value);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static List<String> smembers(String key) {
		Jedis jedis = null;
		Set<String> set = null;
		List<String> ranges = new ArrayList<String>();
		try {
			jedis = pool.getResource();
			set = jedis.smembers(key);
			if (set != null) {
				ranges.addAll(set);
			}
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return ranges;
	}

	public static List<byte[]> smembers(byte[] key) {
		Jedis jedis = null;
		Set<byte[]> set = null;
		List<byte[]> ranges = new ArrayList<byte[]>();
		try {
			jedis = pool.getResource();
			set = jedis.smembers(key);
			if (set != null) {
				ranges.addAll(set);
			}
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return ranges;
	}

	public static List<String> getCacheObjectByKey(String key,
			String... propertyName) {
		Jedis jedis = null;
		List<String> values = null;
		try {
			jedis = pool.getResource();
			values = jedis.hmget(key, propertyName);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return values;
	}

	public static Set<String> keys(String keyPattern) {
		Jedis jedis = null;
		Set<String> keys = null;
		try {
			jedis = pool.getResource();
			keys = jedis.keys(keyPattern);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return keys;
	}

	public static long del(String key) {
		Jedis jedis = null;
		long delCount = 0l;
		try {
			jedis = pool.getResource();
			delCount = jedis.del(key);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return delCount;
	}

	public static Set<Tuple> zrangeByScoreWithScores(String key, Double min,
			Double max) {
		Jedis jedis = null;
		Set<Tuple> ranges = new HashSet<Tuple>();
		try {
			jedis = pool.getResource();
			ranges = jedis.zrangeByScoreWithScores(key, min, max);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return ranges;
	}

	public static void zRem(String key, String field) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.zrem(key, field);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static int zcard(String key) {
		Jedis jedis = null;
		int count = 0;
		try {
			jedis = pool.getResource();
			count = jedis.zcard(key).intValue();
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return count;
	}

	public static List<String> lrange(String key, int start, int end) {
		List<String> values = null;
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			values = jedis.lrange(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return values;
	}

	public static void sadd(String key, String... members) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.sadd(key, members);
		} catch (Exception e) {
			e.printStackTrace();
			pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static void sadd(byte[] key, byte[] member) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.sadd(key, member);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static void srem(String key, String... members) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.srem(key, members);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static void srem(byte[] key, byte[] member) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.srem(key, member);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static long incr(String key, Long gap) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			return jedis.incrBy(key, gap);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
		} finally {
			returnResource(pool, jedis);
		}
		return 0;
	}

	public static boolean getDistributeKLock(String key) {
		long value = incr(key, 1L);
		return value == 1;
	}
	
	public static boolean sismember(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			return jedis.sismember(key, member);
		} catch (Exception e) {
			e.printStackTrace();
			//pool.returnBrokenResource(jedis);
			return false;
		} finally {
			returnResource(pool, jedis);
		}
	}
	
	public static void hset(String key, String field, String value){
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.hset(key, field, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static String hget(String key, String field){
		Jedis jedis = null;
		String value = null;
		try {
			jedis = pool.getResource();
			value = jedis.hget(key, field);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
		if (value == null)
			return "0";
		return value;
	}

	public static void hdel(String key, String... field){
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.hdel(key, field);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
	}
	
	public static void hmset(String key, Map<String, String> cacheMap){
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.hmset(key, cacheMap);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
	}

	public static Map<String, String> hgetAll(String key){
		Jedis jedis = null;
		Map<String, String> map = null;
		try {
			jedis = pool.getResource();
			map = jedis.hgetAll(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
		if (map == null) {
			return new HashMap<String, String>();
		}
		return map;
	}



	public static long lrem(String key, String value) {
		Jedis jedis = null;
		long count = 0l;
		try {
			jedis = pool.getResource();
			count = jedis.lrem(key, 0, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
		return count;
	}
	
	public static long zcount(String key, Double max, Double min) {
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			return jedis.zcount(key, min, max);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		} finally {
			returnResource(pool, jedis);
		}
	}
	
	
	public static Set<String> zrevrangeByScore(String key, Double max, Double min, int offset, int count) {
		Jedis jedis = null;
		Set<String> ranges = new HashSet<String>();
		try {
			jedis = pool.getResource();
			ranges = jedis.zrevrangeByScore(key, max, min, offset, count);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
		return ranges;
	}

	/**
	 * 设置过期时间
	 * @param key
	 * @param seconds
	 */
	public static void expire(String key,int seconds){
		Jedis jedis = null;
		try {
			jedis = pool.getResource();
			jedis.expire(key,seconds);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(pool,jedis);
		}
	}
}
